﻿using System;
using System.Collections;
using System.Linq;
using System.Web.UI;
using NativeCode.Core.Data;
using NativeCode.Web.Controls.Filters;

namespace NativeCode.Web.Controls
{
	/// <summary>
	/// Takes whatever type is passed in and tries to determine if it's a generic server
	/// control or not. If it is, we pass the generic type to the Init method. If not,
	/// we do whatever ASP.NET was going to do with it anyway.
	/// </summary>
	public class GenericControlBuilder : ControlBuilder
	{
		private const string TypeAttributeName = "ObjectType";

		public override void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string id, IDictionary attribs)
		{
			if (type.GetCustomAttributes(typeof (ControlBuilderAttribute), false)
				.OfType<ControlBuilderAttribute>()
				.Any(cb => cb.BuilderType.FullName == typeof (GenericControlBuilder).FullName)
				)
			{
				if (attribs.Contains(TypeAttributeName) && type.BaseType != null)
				{
					string objectTypeName = (string) attribs[TypeAttributeName];

					Type baseType = type.BaseType.GetGenericTypeDefinition();
					Type baseTypeArgs = FilterableTypesRegistry.RegisteredTypes.SingleOrDefault(t => t.FullName == objectTypeName);
					if (baseTypeArgs == null)
					{
						baseTypeArgs = Type.GetType(objectTypeName, true, true);
					}

					if (baseType != null && baseTypeArgs != null)
					{
						attribs.Remove(TypeAttributeName);
						Type genericType = baseType.MakeGenericType(baseTypeArgs);
						base.Init(parser, parentBuilder, genericType, tagName, id, attribs);
						return;
					}
				}
			}

			// Important that we let all other cases call the default builder's Init.
			base.Init(parser, parentBuilder, type, tagName, id, attribs);
		}
	}
}